package com.xgf.redis.config.util;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * 
 * @author xgf
 * @date 2020/03/02
 */
public class RedisLockUtils {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockUtils.class);

	public static final String ORDER_LOCK_PREFIX = "ORDER_LOCK:";
	public static final long ORDER_STATUS_EXPIRE = 2*24*60*60;
	public static final long ORDER_NO_EXPIRE = 20*60;
	public static final long ORDER_LOCK_EXPIRE = 2;
    public static final String ORDER_STATUS_PREFIX = "ORDER_STATUS:";
    public static final String ORDER_NO_PREFIX = "WXORDER_NO:";
    

	/**
	 * 获取redis分布式锁
	 * @author jiangheyu
	 * @return
	 */
	public static boolean getRedisLock(StringRedisTemplate redisTemplate, String lockKey,Long expireTime, TimeUnit timeUnit,String val) {
		LOGGER.info("获取redis分布式锁开始, key: {}, val: {}",lockKey,val);
		
		try {
			boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, val);
			if (lock) {
				redisTemplate.expire(lockKey,expireTime, timeUnit); //成功设置过期时间
				LOGGER.info("获取redis分布式锁成功, 并设置过期时间:{},类型:{}",expireTime,timeUnit);
				return true;
			}
			
		} catch(Exception e) {
			LOGGER.error("获取redis分布式锁异常, 异常信息为:{}",e.toString());
			if(redisTemplate.hasKey(lockKey)) {
				LOGGER.error("获取redis分布式锁存在");
				String lockVal = redisTemplate.opsForValue().get(lockKey);
				if(val.equals(lockVal)) {
					redisTemplate.delete(lockKey);
					LOGGER.error("获取redis分布式锁异常,锁存在并且归属与当前线程进行锁删除操作!");
				}
			}
		} finally {
			int lockExpireTime = redisTemplate.getExpire(lockKey, timeUnit).intValue();
			if(lockExpireTime ==-1 || lockExpireTime > expireTime) {
				LOGGER.debug("redis 锁 key:{}, 过期时间:{} 过期时间单位:{}, 设置过期时间!!!",lockKey,expireTime,timeUnit);
				redisTemplate.expire(lockKey,expireTime, timeUnit); //成功设置过期时间
			}
		}
		LOGGER.info("获取redis分布式锁失败!!!");
		return false;
		
	}
	
	/**
	 * 主动 删除分布式锁
	* @Title: deleteRedisLock
	* @Description: TODO
	* @param @param redisTemplate redis 处理类
	* @param @param lockKey 锁的key
	* @param @param expireTime 锁的存在时间
	* @param @param timeUnit 锁的时间单位
	* @param @param val 锁的值 如果这个值 和 锁中的val 一样证明是我设置的锁
	* @return void
	* @throws
	 */
	public static void deleteRedisLock(StringRedisTemplate redisTemplate, String lockKey,Long expireTime, TimeUnit timeUnit,String val) {

		if(redisTemplate.hasKey(lockKey)) {
			String lockVal = redisTemplate.opsForValue().get(lockKey);
			if(val.equals(lockVal)) {
				redisTemplate.delete(lockKey);
				LOGGER.error("执行业务处理完成(异常或正常), 并且判断锁归属与本线程, 执行删除锁操作成功,lockKey:{}",lockKey);
			}
			int expire = redisTemplate.getExpire(lockKey, TimeUnit.SECONDS).intValue();
			if(expire==-1) {
				redisTemplate.expire(lockKey, 20L, TimeUnit.SECONDS);
			}
		}
	
	}
}
